﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;

namespace SPTraceViewUpdate
{
    internal partial class Updater
    {
        public bool PrepareToUpdate()
        {
            return true;
        }

        public bool Update(UpdateInfo updateInfo)
        {
            if (updateInfo != null)
            {
                int fileId = 0;
                //foreach (XmlNode fileNode in updateInfo.ChildNodes)
                //{
                //    if ("File".Equals(fileNode.Name))
                //    {
                //        string location = fileNode.Attributes["Path"].Value;
                string localFile = Path.GetFullPath(m_InstallPath + "//" + Path.GetFileName(updateInfo.FileUrl));

                Uri fileUri = null;

                //MFD: we need to support both full and relative urls for back compatibility.
                if (updateInfo.FileUrl.StartsWith("http"))
                    fileUri = new Uri(updateInfo.FileUrl);
                else
                    fileUri = new Uri(UPDATE_LOCATION + updateInfo.FileUrl.TrimStart(new char[] { '/' }));

                fileId++;

                HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(fileUri);
                httpRequest.Method = "GET";
                httpRequest.Timeout = 1200000; //1200 sec = 20 min

                HttpWebResponse response = null;

                try
                {
                    response = (HttpWebResponse)httpRequest.GetResponse();

                    Stream streamResponse = response.GetResponseStream();

                    try
                    {
                        bool allGood = false;
                        int attempts = 0;

                        bool isZipFile = ".zip".Equals(Path.GetExtension(localFile), StringComparison.InvariantCultureIgnoreCase);
                        if (isZipFile)
                            localFile = Path.ChangeExtension(localFile, ".exe");

                        Exception fileDelException = null;
                        do
                        {
                            try
                            {
                                if (File.Exists(localFile))
                                    File.Delete(localFile);

                                allGood = true;
                                fileDelException = null;
                            }
                            catch (Exception ex)
                            {
                                fileDelException = ex;
                                System.Threading.Thread.Sleep(500);
                            }

                            attempts++;
                        }
                        while (!allGood && attempts < 10);

                        if (fileDelException != null)
                        {
                            return false;
                        }

                        if (isZipFile)
                        {
                            using (MemoryStream memStr = new MemoryStream())
                            using (BinaryReader reader = new BinaryReader(streamResponse))
                            using (BinaryWriter writer = new BinaryWriter(memStr))
                            {
                                byte[] chunk = null;
                                do
                                {
                                    chunk = reader.ReadBytes(1024);
                                    writer.Write(chunk);
                                }
                                while (chunk != null && chunk.Length == 1024);

                                writer.Flush();

                                Unzip.UnZip(memStr, m_InstallPath, false);
                            }
                        }
                        else
                        {
                            using (BinaryReader reader = new BinaryReader(streamResponse))
                            using (BinaryWriter writer = new BinaryWriter(new FileStream(localFile, FileMode.Create)))
                            {
                                byte[] chunk = null;
                                do
                                {
                                    chunk = reader.ReadBytes(1024);
                                    writer.Write(chunk);
                                }
                                while (chunk != null && chunk.Length == 1024);

                                writer.Flush();
                            }
                        }
                    }
                    finally
                    {
                        streamResponse.Close();
                    }

                }
                finally
                {
                    // Close response
                    if (response != null)
                        response.Close();
                }


                return true;
            }

            return false;
        }
    }
}
